package com.epoch.base.function;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import com.epoch.base.intercepter.EpochI18nInterceptor;
import com.epoch.base.model.BaseModel;
import com.epoch.base.tag.HTMLTag;
import com.epoch.base.util.DateUtils;
import com.epoch.base.util.ExtStringUtils;
import com.epoch.base.util.LoggerUtil;
import com.epoch.platform.sys.dict.dao.SysDict;
import com.epoch.platform.sys.dict.service.SysDictService;
import com.epoch.platform.sys.info.dao.SysInfoDao;
import com.epoch.platform.sys.menu.dao.SysMenu;
import com.jfinal.kit.JsonKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.redis.Redis;

public class BeetlFunctions {
	
	static SysDictService sysDictService = new SysDictService();
	
	private static final String SYS_DICT_ITEM_CODE = "item_code";
    private static final String SYS_DICT_ITEM_VALUE = "item_value";
    private static final String FILTER_CODE_KEY = "id";
    private static final String FILTER_VALUE_KEY = "text";
    
    private static final String INIT_MENU_CODE_CACHE = "initMenuCodeCache";
    
    private static final String INIT_SYSTEMINFO_CACHE = "initSysteminfoCache";
    
    public String formatDate(Date o, String args) {
        return DateUtils.getDateToString(o, args);
    }
    
    public String formatDate(String date, String args) {
        return date;
    }
	
    public static Map<String, List<HTMLTag>> buildMoreBtnMap(List<HTMLTag> moreBtns, int cnt) {
        Map<String, List<HTMLTag>> map = new HashMap<String, List<HTMLTag>>();
        if (moreBtns != null) {
            for (HTMLTag moreBtn : moreBtns) {
                String key = "OTH";
                Object positionObj = moreBtn.get("position");
                if (positionObj != null && positionObj instanceof String) {
                    try {
                        Integer posi = Integer.valueOf((String) positionObj);
                        int posiInt = posi.intValue();
                        if (posiInt >= 0 && posiInt < cnt) {
                            key = String.valueOf(posiInt);
                        }
                    } catch (NumberFormatException e) {
                        e.getClass();
                    }
                }
                List<HTMLTag> list = map.get(key);
                if (list == null) {
                    list = new ArrayList<HTMLTag>();
                    map.put(key, list);
                }
                list.add(moreBtn);
            }
        }
        return map;
    }
    
    public static String getCurLocale() {
        return EpochI18nInterceptor.getCurLocale();
    }
    
    public static Map<String, String> getDictCode(String dictCode) {
        List<SysDict> sysDictList = sysDictService.findSysDictInfoByDictCode(dictCode);
        Map<String, String> dictCodeMap = new LinkedHashMap<String, String>();
        if (sysDictList != null) {
            for (SysDict sysDict : sysDictList) {
                dictCodeMap.put(sysDict.getStr(SysDict.ITEM_CODE), sysDict.getStr(SysDict.ITEM_VALUE));
            }
        }
        return dictCodeMap;
    }
    
    /**
     * 数据字典获取方法,国际化翻译
     *
     * @param dictCode dic_code值
     * @param key      item_code值
     * @return Map
     */
    public static String getDictCode(String dictCode, String key) {
        if (StringUtils.isBlank(key)) {
            return null;
        }
        List<SysDict> sysDictList = sysDictService.findSysDictInfoByDictCode(dictCode);
        String value = null;
        if (sysDictList != null) {
            for (SysDict sysDict : sysDictList) {
                if (key.equals(sysDict.getStr(SYS_DICT_ITEM_CODE))) {
                    value = sysDict.getStr(SYS_DICT_ITEM_VALUE);
                    break;
                }
            }
        }
        return value;
    }
    
    public static String escapeHtml(String str) {
        return ExtStringUtils.escapeHtml(str);
    }
    
    public static String escapeForQuot(String str) {
        return ExtStringUtils.escapeForJsStr(str);
    }

    public static String escapeForQuot(String str, String quotChar) {
        return ExtStringUtils.escapeForJsStr(str, quotChar);
    }
    
    /**
     * 获取数据字典列表JSON字符串用于table中的filterData属性
     *
     * @param dictCode    数据字典code
     * @param blankOption 是否在列表最前面添加空选项
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForFilter(String dictCode, boolean blankOption) {
        return dictForFilter(dictCode, blankOption, "", "");
    }

    /**
     * 获取数据字典列表JSON字符串用于table中的filterData属性
     *
     * @param dictCode 数据字典code
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForFilter(String dictCode) {
        return dictForFilter(dictCode, false);
    }

    /**
     * 获取数据字典列表JSON字符串用于table中的editorData属性
     *
     * @param dictCode      数据字典code
     * @param blankOption   是否在列表最前面添加空选项
     * @param blankOptCode  空选项的code值
     * @param blankOptValue 空选项的value值
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForEditor(String dictCode, boolean blankOption, String blankOptCode, String blankOptValue) {
        return dictForFilter(dictCode, blankOption, blankOptCode, blankOptValue);
    }
    
    /**
     * 获取数据字典列表JSON字符串用于table中的editorData属性
     *
     * @param dictCode    数据字典code
     * @param blankOption 是否在列表最前面添加空选项
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForEditor(String dictCode, boolean blankOption) {
        return dictForEditor(dictCode, blankOption, "", "");
    }

    /**
     * 获取数据字典列表JSON字符串用于table中的editorData属性
     *
     * @param dictCode 数据字典code
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForEditor(String dictCode) {
        return dictForEditor(dictCode, false);
    }
    
    /**
     * 获取数据字典列表JSON字符串用于table中的filterData属性
     *
     * @param dictCode      数据字典code
     * @param blankOption   是否在列表最前面添加空选项
     * @param blankOptCode  空选项的code值
     * @param blankOptValue 空选项的value值
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String dictForFilter(String dictCode, boolean blankOption, String blankOptCode, String blankOptValue) {
        return getDictJson(dictCode, FILTER_CODE_KEY, FILTER_VALUE_KEY, blankOption, blankOptCode, blankOptValue);
    }
    
    /**
     * 获取数据字典列表JSON字符串
     *
     * @param dictCode      数据字典code
     * @param codeKey       结果JSON内字典code键名
     * @param valueKey      结果JSON内字典value键名
     * @param blankOption   是否在列表最前面添加空选项
     * @param blankOptCode  空选项的code值
     * @param blankOptValue 空选项的value值
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String getDictJson(String dictCode, String codeKey, String valueKey, boolean blankOption,
                                     String blankOptCode, String blankOptValue) {
        List<SysDict> sysDictList = sysDictService.findSysDictInfoByDictCode(dictCode);
        return listToKvJson(sysDictList, codeKey, SYS_DICT_ITEM_CODE, valueKey, SYS_DICT_ITEM_VALUE, blankOption,
                blankOptCode, blankOptValue);
    }

    /**
     * 获取数据字典列表JSON字符串
     *
     * @param dictCode    数据字典code
     * @param codeKey     结果JSON内字典code键名
     * @param valueKey    结果JSON内字典value键名
     * @param blankOption 是否在列表最前面添加空选项
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String getDictJson(String dictCode, String codeKey, String valueKey, boolean blankOption) {
        return getDictJson(dictCode, codeKey, valueKey, blankOption, "", "");
    }

    /**
     * 获取数据字典列表JSON字符串，默认在列表最前不添加空选项
     *
     * @param dictCode 数据字典code
     * @param codeKey  结果JSON内字典code键名
     * @param valueKey 结果JSON内字典value键名
     * @return 指定code的数据字典列表JSON字符串
     */
    public static String getDictJson(String dictCode, String codeKey, String valueKey) {
        return getDictJson(dictCode, codeKey, valueKey, false);
    }
    
    /**
     * 将对象list转换为JSON字符串
     *
     * @param list        对象list
     * @param codeKey     结果JSON内code值键名
     * @param codeField   结果JSON内code值对应字段名
     * @param valueKey    结果JSON内value值键名
     * @param valueField  结果JSON内value值对应字段名
     * @param blankOption 是否在列表最前面添加空选项
     * @return 转换后的JSON字符串
     */
    public static String listToKvJson(List<? extends Object> list, String codeKey, String codeField, String valueKey,
                                      String valueField, boolean blankOption) {
        return listToKvJson(list, codeKey, codeField, valueKey, valueField, blankOption, "", "");
    }

    /**
     * 将对象list转换为JSON字符串
     *
     * @param list       对象list
     * @param codeKey    结果JSON内code值键名
     * @param codeField  结果JSON内code值对应字段名
     * @param valueKey   结果JSON内value值键名
     * @param valueField 结果JSON内value值对应字段名
     * @return 转换后的JSON字符串
     */
    public static String listToKvJson(List<? extends Object> list, String codeKey, String codeField, String valueKey,
                                      String valueField) {
        return listToKvJson(list, codeKey, codeField, valueKey, valueField, false);
    }
    

    /**
     * 将对象list转换为JSON字符串
     *
     * @param list          对象list
     * @param codeKey       结果JSON内code值键名
     * @param codeField     结果JSON内code值对应字段名
     * @param valueKey      结果JSON内value值键名
     * @param valueField    结果JSON内value值对应字段名
     * @param blankOption   是否在列表最前面添加空选项
     * @param blankOptCode  空选项的code值
     * @param blankOptValue 空选项的value值
     * @return 转换后的JSON字符串
     */
    public static String listToKvJson(List<? extends Object> list, String codeKey, String codeField, String valueKey,
                                      String valueField, boolean blankOption, String blankOptCode, String blankOptValue) {
        List<Map<String, String>> jsonMapList = new ArrayList<Map<String, String>>();
        if (blankOption) {
            Map<String, String> blankMap = new HashMap<String, String>();
            blankMap.put(codeKey, blankOptCode);
            blankMap.put(valueKey, blankOptValue);
            jsonMapList.add(blankMap);
        }
        if (list != null) {
            for (Object obj : list) {
                String code = obtainFieldStrValue(obj, codeField);
                String value = obtainFieldStrValue(obj, valueField);
                Map<String, String> jsonMap = new HashMap<String, String>();
                jsonMap.put(codeKey, code);
                jsonMap.put(valueKey, value);
                jsonMapList.add(jsonMap);
            }
        }
        return toJson(jsonMapList);
    }
    
    public static String toJson(Object obj) {
        String json = null;
        if (obj != null) {
            json = JsonKit.toJson(obj);
        }
        return json;
    }
    
    private static String obtainFieldStrValue(Object obj, String field) {
        String result = null;
        if (obj != null && field != null) {
            if (obj instanceof Model) {
                Object val = ((Model<?>) obj).get(field);
                if (val != null) {
                    result = val.toString();
                }
            } else if (obj instanceof Record) {
                Object val = ((Record) obj).get(field);
                if (val != null) {
                    result = val.toString();
                }
            } else {
                try {
                    result = BeanUtils.getNestedProperty(obj, field);
                } catch (Exception e) {
                    
                }
            }
        }
        return result;
    }
    
    public static void initMenuCode() {
        List<SysMenu> sysMenus = SysMenu.dao.find(Db.getSql("systemManage.initMenuCode"));
        Map<Object, Object> menuCode = new HashMap<>();
        for (SysMenu sysMenu : sysMenus) {
            String key = sysMenu.getStr(SysMenu.MENU_CODE);
            menuCode.put(key, sysMenu.getStr(SysMenu.MENU_NAME));
        }
        Redis.use().hmset(INIT_MENU_CODE_CACHE, menuCode);
    }
    
    public static String getMenuNameByCode(String menuCode) {
        if (StringUtils.isBlank(menuCode)) {
            return null;
        }
        LoggerUtil.getLogger().info("-##getMenuNameByCode menuCode:{}", menuCode);
        List menuName = Redis.use().hmget(INIT_MENU_CODE_CACHE, menuCode);
        if (CollectionUtils.isNotEmpty(menuName)) {
            String resultName = menuName.get(0) == null ? null : menuName.get(0).toString();
            LoggerUtil.getLogger().info("-##getMenuNameByCode 缓存中取出 menuCode :{}，一共有{}条，第一个值：{}", menuCode, menuName.size(), resultName);
            return resultName;
        }
        return null;

    }
    
    public static void initSystemInfo() {
        List<SysInfoDao> sysInfolist = SysInfoDao.dao.find(" select info_title,info_desc from sys_info where INFO_TYPE='1' and status='ENABLE' ");
        String infoText = "";
        if (sysInfolist != null && sysInfolist.size() > 0) {
            for (int i = 0; i < sysInfolist.size(); i++) {
                infoText += (i + 1) + " . " + sysInfolist.get(i).getStr(SysInfoDao.INFO_TITLE) + " : " + sysInfolist.get(i).getStr(SysInfoDao.INFO_DESC) + " ;  ";
            }
        }
        Redis.use().set(INIT_SYSTEMINFO_CACHE, infoText);
    }
    
    public static String getSystemInfo() {
        String info = Redis.use().get(INIT_SYSTEMINFO_CACHE);
        return info;
    }
    
    /**
     * 先List对象转换为Map，提供select标签使用
     * 使用场景：
     * 将一张记录作为下拉选项选值时使用这个方法
     * eg:
     * 后台使用：
     * List<sysMenu> menuList = sysMeun.dao.find("sql");
     * //转换结果值
     * Map result = BeetlFunctions.getListToMap(menuList,'id','name');
     * 前台使用：
     * <bs:select list="${lisFun.getListToMap(menuList,'id','name')}" name="budgetAccountSet.OWNING_ORGANIZATION_TYPE"
     * value="${budgetAccountSet.OWNING_ORGANIZATION_TYPE}"></bs:select>
     *
     * @param result   结果值
     * @param codeKey  key名称
     * @param valueKey value名称
     * @return map
     */
    @SuppressWarnings("rawtypes")
    public static Map<String, String> getListToMap(List<? extends BaseModel> result, String codeKey, String valueKey) {
        Map<String, String> dictCodeMap = new LinkedHashMap<String, String>();
        if (CollectionUtils.isNotEmpty(result)) {
            for (BaseModel baseModel : result) {
                String codeKeyTemp = baseModel.get(codeKey).toString();
                String valueKeyTemp = baseModel.get(valueKey).toString();
                dictCodeMap.put(codeKeyTemp, valueKeyTemp);
            }
        }
        return dictCodeMap;
    }
}
